package com.chao.demo.test.ThreadImplements;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 线程池
 */
public class UseExecutors implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " run() 方法执行中...");
    }

    /**
     * Executors 提供了一系列工厂方法用于创先线程池，返回的线程池都实现了
     * ExecutorService 接口。
     * 主要有
     * newSingleThreadExecutor：创建一个单线程的线程池。这个线程池只有一
     * 个线程在工作，也就是相当于单线程串行执行所有任务。如果这个唯一的线程因
     * 为异常结束，那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺
     * 序按照任务的提交顺序执行。
     * newFixedThreadPool：创建固定大小的线程池。每次提交一个任务就创建一
     * 个线程，直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保
     * 持不变，如果某个线程因为执行异常而结束，那么线程池会补充一个新线程。如
     * 果希望在服务器上使用线程池，建议使用 newFixedThreadPool 方法来创建线程池，
     * 这样能获得更好的性能。
     * newCachedThreadPool：创建一个可缓存的线程池。如果线程池的大小超过
     * 了处理任务所需要的线程，那么就会回收部分空闲（60 秒不执行任务）的线程，
     * 当任务数增加时，此线程池又可以智能的添加新线程来处理任务。此线程池不会
     * 对线程池大小做限制，线程池大小完全依赖于操作系统（或者说 JVM）能够创建
     * 的最大线程大小。
     * newScheduledThreadPool：创建一个大小无限的线程池。此线程池支持定时
     * 以及周期性执行任务的需求。
     * tidying
     */

    /**
     *  RUNNING：这是最正常的状态，接受新的任务，处理等待队列中的任务。
     *  SHUTDOWN：不接受新的任务提交，但是会继续处理等待队列中的任务。
     *  STOP：不接受新的任务提交，不再处理等待队列中的任务，中断正在执行任务的线程。
     *  TIDYING：所有的任务都销毁了，workCount 为 0，线程池的状态在转换为
     *  TIDYING 状态时，会执行钩子方法 terminated()。
     *  TERMINATED：terminated()方法结束后，线程池的状态就会变成这个。
     */

    /**
     * 线程池中 submit() 和 execute() 方法有什么区别？
     * 接收参数：execute()只能执行 Runnable 类型的任务。submit()可以执行
     * Runnable 和 Callable 类型的任务。
     * 返回值：submit()方法可以返回持有计算结果的 Future 对象，而 execute()没有
     * 异常处理：submit()方便 Exception 处理
     */

}

class SingleThreadExecutorTest {

    public static void main(String[] args) {
        // 创建newSingleThreadExecutor
        // ExecutorService executorService = Executors.newSingleThreadExecutor();
        // UseExecutors runnableTest = new UseExecutors();
        // for (int i = 0; i < 5; i++) {
        //     executorService.execute(runnableTest);
        // }
        // System.out.println("线程任务开始执行");
        // executorService.shutdown();

        // newFixedThreadPool
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executorService.execute(()->{
                System.out.println("123");
            });
        }
    }
}
